package com.arvato.wxwork.controller.admin.staff;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.arvato.common.config_bean.FilehomeConfig;
import com.arvato.common.config_bean.WxworkConfig;
import com.arvato.common.util.ExcelUtil;
import com.arvato.common.util.JdomUtil;
import com.arvato.common.util.JsonUtil;
import com.arvato.common.wx.crypt.AesException;
import com.arvato.common.wx.crypt.WXBizMsgCrypt;
import com.arvato.minipro.bean.bean_dto.common.PageData;
import com.arvato.minipro.bean.bean_dto.common.Query;
import com.arvato.minipro.bean.bean_dto.common.Result;
import com.arvato.minipro.controller.BaseController;
import com.arvato.wxwork.bean.bean_do.staff.WxworkStaffInfoDo;
import com.arvato.wxwork.bean.bean_vo.member.WxworkExternalInfoVo;
import com.arvato.wxwork.bean.bean_vo.staff.WxworkStaffInfoVo;
import com.arvato.wxwork.service.member.WxworkExternalService;
import com.arvato.wxwork.service.staff.WxworkDepartmentService;
import com.arvato.wxwork.service.staff.WxworkStaffInfoService;

import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;


/**
 * 后台系统的员工管理
 * 和企业微信通讯录相联通的controller
 * 按理说应该禁用掉企业微信原生的编辑和删除 但是因为一些原因无法禁用掉
 * 所以如果在企业微信原生后台新增人员 都不同步到本地 直接调用接口删除
 * 同步的时候 凡是和本地信息不一样的 全部都按照本地员工信息为准
 * 凡是存在本地没有的线上人员 全部删除
 * @author ZHAN655
 *
 */
@Controller
@RequestMapping("/admin/wxwork/staff/")
public class WxworkStaffController extends BaseController{
	
	private Logger logger = LoggerFactory.getLogger(WxworkStaffController.class);

	@Autowired
	private JsonUtil jsonUtil;
	@Autowired
	private WxworkStaffInfoService wxworkStaffInfoService;

	@Autowired
	private WxworkExternalService wxworkExternalService;
	
	@Autowired
	private WxworkDepartmentService wxworkDepartmentService;

	/**
	 * 获取企业微信员工列表
	 * @param req
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="/list")
	public PageData listStaff(HttpServletRequest req, @RequestParam Map<String, Object> param) {
		Query query = new Query(param);
		logger.info("获取员工列表");
		PageData pageData = wxworkStaffInfoService.listStaffByQuery(query, query.getPageNum(), query.getPageSize());
		return pageData;
	}
	
	/**
	 * 获取一个员工的详情
	 * @param req
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="/detail")
	public Result staffDetail(String staffId) {
		WxworkStaffInfoVo staffInfoVo = wxworkStaffInfoService.getStaffById(staffId);
		return Result.success(staffInfoVo);
	}
	
	
	/**
	 * 解析品牌给的Excel员工表 得到员工数据 存在本地数据库
	 * @param file
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/import")
	public Result importStaff(@RequestParam("file") MultipartFile file){
		// 先把文件存储起来 存储到本地
		String fileName =  + System.currentTimeMillis() + "." + file.getOriginalFilename().split("\\.")[1];
		if(!fileName.endsWith("xls") && !fileName.endsWith("xlsx")) {
			// 如果不是excel文件 直接返回上传失败
			return Result.fail("仅支持Excel文件类型。");
		}
		// 先确保服务器上有 FilehomeConfig.FILEHOME 这么一个文件夹
		File excelFile = new File(FilehomeConfig.FILEHOME + fileName);
		try {
			if(!excelFile.exists()) {
				excelFile.createNewFile();
				file.transferTo(excelFile);
			}
		} catch (IllegalStateException | IOException e) {
			e.printStackTrace();
			logger.error("Excel文件上传保存失败。");
			return Result.fail("Excel文件上传保存失败。");
		}
		// 读取Excel 得到数据
		List<WxworkStaffInfoDo> staffList = null;
		try {
			staffList = ExcelUtil.readStaffExcel(excelFile);
			if(staffList == null || staffList.size() == 0) {
				return Result.fail("Excel解析失败，或者Excel不存在员工数据");
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		// 存储这些员工信息到本地数据库
		List<WxworkStaffInfoDo> failList = new ArrayList<WxworkStaffInfoDo>();
		for(WxworkStaffInfoDo wxworkStaffInfoDo : staffList) {
			// 验证员工号 姓名 职位 部门编号 部门名称是否都存在
			String staffCode = wxworkStaffInfoDo.getStaffCode();
			String name = wxworkStaffInfoDo.getName();
			String position = wxworkStaffInfoDo.getPosition();
			String departmentName = wxworkStaffInfoDo.getDepartmentName();
			String departmentCode = wxworkStaffInfoDo.getDepartmentCode();
			if(staffCode == null || staffCode.trim().equals("") ||
				name == null || name.trim().equals("") ||
				position == null || position.trim().equals("") ||
				departmentName == null || departmentName.trim().equals("") ||
				departmentCode == null || departmentCode.trim().equals("")) {
				failList.add(wxworkStaffInfoDo);
				continue;
			}
			// 检查当前员工是否存在
			WxworkStaffInfoVo staffVo = wxworkStaffInfoService.checkLocalStaffExist(staffCode);
			if(staffVo != null) {
				failList.add(wxworkStaffInfoDo);
				continue;
			}
			try {
				wxworkStaffInfoDo.setBrand("AUPRES");
				wxworkStaffInfoDo.setCreateTime(new Date());
				wxworkStaffInfoDo.setEnable(1);
				wxworkStaffInfoDo.setStatus(4);
				int row = wxworkStaffInfoService.insert(wxworkStaffInfoDo);
				if(row == 0) {
					failList.add(wxworkStaffInfoDo);
				}
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("员工导入失败", e);
				failList.add(wxworkStaffInfoDo);
			}
		}
		if(failList.size() >= 1) {
			return Result.fail("成功导入" + (staffList.size() - failList.size()) + "人，" + failList.size() + "人导入失败", failList);
		}
		return Result.success("导入成功，一共导入" + staffList.size() + "人。", null);
	}
	
	/**
	 * 新增员工
	 * @param wxworkStaffInfoDo
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/insert")
	public Result insert(WxworkStaffInfoDo wxworkStaffInfoDo){
		// 新增之前先检查新增的员工是否存在
		WxworkStaffInfoVo staffVo = wxworkStaffInfoService.checkLocalStaffExist(wxworkStaffInfoDo.getStaffCode());
		if(staffVo != null) {
			return Result.fail("创建员工失败，当前员工号已存在。");
		}
		try {
			wxworkStaffInfoDo.setBrand("AUPRES");
			wxworkStaffInfoDo.setCreateTime(new Date());
			wxworkStaffInfoDo.setEnable(1);
			// 新增的都是未激活的 4：未激活
			wxworkStaffInfoDo.setStatus(4);
			int row = wxworkStaffInfoService.insert(wxworkStaffInfoDo);
			if(row == 1) {
				return Result.success("创建员工成功。");
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("创建员工失败", e);
			return Result.fail("创建员工失败" + e.getMessage());
		}
		return Result.fail("创建员工失败");
	}
	
	/**
	 * 根据code查询员工信息
	 * @param storeId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/code")
	public Result checkCode(String staffCode){
		// 检查当前的员工号是不是正式合法的
		Query query = new Query();
		query.put("staffCode", staffCode);
		WxworkStaffInfoVo staffInfoVo = wxworkStaffInfoService.checkLocalStaffExist(staffCode);
		if(staffInfoVo == null) {
			// 如果当前员工号不存在本地 那么就是一个非法的员工号
			return Result.fail("员工号验证失败，请联系管理员将你的员工号录入系统。");
		}
		return Result.success(staffInfoVo);
	}
	/**
	 * 员工进入企业微信的时候，需要二次验证员工
	 * @param storeId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/verify")
	public Result staffAuth(String staffCode, String code){
		// 检查当前的员工号是不是正式合法的
		Query query = new Query();
		query.put("staffCode", staffCode);
		WxworkStaffInfoVo staffInfoVo = wxworkStaffInfoService.checkLocalStaffExist(staffCode);
		if(staffInfoVo == null) {
			// 如果当前员工号不存在本地 那么就是一个非法的员工号
			return Result.fail("员工号验证失败，请联系管理员将你的员工号录入系统。");
		}
		// 检查当前的员工号是否存在线上
		String userid = wxworkStaffInfoService.checkRemoteStaffExist(staffCode);
		if(userid != null) {
			// 员工第一次进入企业微信的时候，线上竟然已经存在了此员工！ 返回信息 让管理员自己去操作
			return Result.fail("当前员工号已经存在于企业微信，请联系管理员。");
		}
		try {
			userid = wxworkStaffInfoService.authSucc(code);
			if(userid == null) {
				return Result.fail("员工号验证失败，请联系管理员");
			}
			// 认证成功 微信返回该员工对应的userid 更新本地的userid 并且将本员工的部门相关的信息 更新到远程
			WxworkStaffInfoDo staffInfoDo = new WxworkStaffInfoDo();
			staffInfoDo.setStaffId(staffInfoVo.getStaffId());
			staffInfoDo.setUserid(userid);
			staffInfoDo.setStatus(1);
			staffInfoDo.setUpdateTime(new Date());
			String departmentName = staffInfoVo.getDepartmentCode();
			// 通过部门名称得到部门ID
			int departmentId = wxworkDepartmentService.getDepartmentIdByName(departmentName);
			staffInfoDo.setName(staffInfoVo.getName());
			staffInfoDo.setPosition(staffInfoVo.getPosition());
			staffInfoDo.setDepartment("[" + departmentId +"]");
			staffInfoDo.setStoreCode(staffInfoVo.getStoreCode());
			staffInfoDo.setLeaderCode(staffInfoVo.getLeaderCode());
			staffInfoDo.setLeaderName(staffInfoVo.getLeaderName());
			staffInfoDo.setStaffCode(staffInfoVo.getStaffCode());
			int row = wxworkStaffInfoService.updateAndUpload(staffInfoDo);
			if(row == 1) {
				return Result.success("员工号验证成功，你已成功进入欧珀莱企业微信", null);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return Result.fail("员工号验证失败，请联系管理员;提示：" + e.getMessage());
		}
		return Result.fail("员工号验证失败，请联系管理员");
	}
	
	/**
	 * 更新员工
	 * @param wxworkStaffInfoDo
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/update")
	public Result update(WxworkStaffInfoDo wxworkStaffInfoDo){
		wxworkStaffInfoDo.setUpdateTime(new Date());
		String departmentCode = wxworkStaffInfoDo.getDepartmentCode();
		// 通过部门名称得到部门ID
		int departmentId = wxworkDepartmentService.getDepartmentIdByName(departmentCode);
		if(departmentId == 1) {
			Result.fail("非法的员工部门编号");
		}
		wxworkStaffInfoDo.setDepartment("[" + departmentId +"]");
		try {
			int row = 0;
			// 如果当前员工没有激活 那么userid就是空的 就只更新本地的
			if(wxworkStaffInfoDo.getUserid() == null || wxworkStaffInfoDo.getUserid().equals("")) {
				row = wxworkStaffInfoService.update(wxworkStaffInfoDo);
			}else {
				// 如果当前员工有激活 那么userid就不是空的 就更新线上的
				row = wxworkStaffInfoService.updateAndUpload(wxworkStaffInfoDo);
			}
			if(row == 1) {
				return Result.success("修改员工成功。");
			}
		} catch(DuplicateKeyException e) {
			return Result.fail("修改员工失败,员工号已存在：" + wxworkStaffInfoDo.getStaffCode());
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("修改员工失败", e);
			return Result.fail("修改员工失败" + e.getMessage());
		}
		return Result.fail("修改员工失败");
	}
	
	/**
	 * 离职员工
	 * @param staffId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/quit")
	public Result checkLogin(String staffId){
		try {
			int row = wxworkStaffInfoService.quit(staffId);
			if(row == 1) {
				return Result.success("离职成功");
			}
		} catch (Exception e) {
			e.printStackTrace();
			
			return Result.fail("离职失败" + e.getMessage());
		}
		return Result.fail("离职失败");
	}
	
	/**
	 * 删除员工
	 * @param staffId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/delete")
	public Result delete(String staffId){
		try {
			int row = wxworkStaffInfoService.deleteLocalAndRemote(staffId);
			if(row == 1) {
				return Result.success("删除成功");
			}
		} catch (Exception e) {
			e.printStackTrace();
			return Result.fail("删除失败" + e.getMessage());
		}
		return Result.success("删除失败");
	}
	
	/**
	 * 同步员工信息
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/snyc")
	public Result snycStaff(){
		int total = wxworkStaffInfoService.snycStaff();
		return Result.success("成功同步" + total + "人");
	}
	
	/**
	 * 员工信息导出
	 * @return
	 * @throws IOException 
	 * @throws WriteException 
	 * @throws RowsExceededException 
	 */
	@ResponseBody
	@RequestMapping(value = "/export")
	public Object export() throws RowsExceededException, WriteException, IOException{
		Query query = new Query();
		query.put("order", "DEPARTMENT_NAME desc");
		List<WxworkStaffInfoVo> staffList = wxworkStaffInfoService.listStaffByQuery(query);
		query.clear();
		for(WxworkStaffInfoVo staffInfoVo : staffList) {
			// 查出每个bc的下属客户
			query.put("staffId", staffInfoVo.getStaffId());
			List<WxworkExternalInfoVo> externalList = wxworkExternalService.listExternalByQuery(query);
			staffInfoVo.setExternalList(externalList);
		}
		String fileName = ExcelUtil.writeStaffExcle(staffList);
		return super.download(fileName, "员工列表.xls");
	}
	
	/**
	 * 获取用户相对于企业的openid
	 * @param userid
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/openid")
	public Result getOpenId(String userid) {
		String userId = wxworkStaffInfoService.getOpenId(userid);
		return Result.success(userId);
	}
	
	/**
	 * 企业微信通讯录通知消息的url有效性验证
	 * 接收腾讯发送过来的加密消息 解析得到业务所需的数据
	 * 目前只有当从线上删除人才会同步到本地
	 * @param req
	 * @return
	 * @throws AesException
	 */
	@ResponseBody
	@RequestMapping(value = "/notice")
	public Result notic(HttpServletRequest req) throws AesException {
		WXBizMsgCrypt wxCryptUtil = new WXBizMsgCrypt(WxworkConfig.MAIL_TOKEN, WxworkConfig.MAIL_KEY, WxworkConfig.CORPID);
		String signature = req.getParameter("msg_signature");
		String timestamp = req.getParameter("timestamp");
		String nonce = req.getParameter("nonce");
		String postData = super.getRequestStr(req).trim();
		// 开始解密WX推送数据
		String mingwen = wxCryptUtil.decryptMsg(signature, timestamp, nonce, postData);
		// 解析明文XML 得到所要的值
		Map<String, String> resultMap = JdomUtil.xmlElements(mingwen);
		System.out.println(jsonUtil.obj2String(resultMap));
		logger.info(jsonUtil.obj2String(resultMap));
		// 线上删除的人 在这边也同步一下 将其状态设置为离职状态
		String type = resultMap.get("ChangeType");
		if(type == null || !type.equals("delete_user")) {
			return Result.fail("不是删除操作，不予处理。");
		}
		// 得到删除人的userid
		String userid = resultMap.get("UserID");
		System.out.println(userid);
		// TODO 做业务处理
		return Result.success();
	}
	
	
}

